#include "stdlib.hpp"
#include <purewell/condition.hpp>
#include <purewell/mutex.hpp>

namespace purewell
{

PWConditionAttribute::PWConditionAttribute()
{
#if defined(HAVE_POSIX_CONDITION)
	pthread_condattr_t* pthis(new pthread_condattr_t);
	if ( !pthis ) return;

	if ( 0 != pthread_condattr_init(pthis) )
	{
		delete pthis;
		return;
	}

	m_pData = pthis;
#else
	__PWERRNO_NOIMPL();
#endif

	return;
}

PWConditionAttribute::~PWConditionAttribute()
{
#if defined(HAVE_POSIX_CONDITION)
	if ( m_pData )
	{
		pthread_condattr_t* pthis((pthread_condattr_t*)m_pData);
		pthread_condattr_destroy(pthis);
		delete pthis;
		m_pData = NULL;
	}
#else
	__PWERRNO_NOIMPL();
#endif
}

void
PWConditionAttribute::release(PWConditionAttribute* obj)
{
	delete obj;
}

PWConditionAttribute*
PWConditionAttribute::create(void)
{
#if defined(HAVE_POSIX_CONDITION)
	PWConditionAttribute* ret(new PWConditionAttribute);
	if ( !ret ) return NULL;
	if ( !ret->m_pData )
	{
		delete ret;
		return NULL;
	}

	return ret;
#else
	__PWERRNO_NOIMPL();
	return NULL;
#endif
}

PWCondition*
PWCondition::create(const PWConditionAttribute* pattr)
{
#if defined(HAVE_POSIX_CONDITION)
	PWCondition* ret(new PWCondition(pattr));
	if ( NULL == ret ) return NULL;

	if ( NULL == ret->m_pData )
	{
		delete ret;
		return NULL;
	}

	return ret;
#else
	__PWERRNO_NOIMPL();
	return NULL;
#endif
}

void
PWCondition::release(PWCondition* obj)
{
	delete obj;
}

PWCondition::PWCondition(const PWConditionAttribute* pattr)
{
#if defined(HAVE_POSIX_CONDITION)
	pthread_cond_t* pthis(new pthread_cond_t);
	if ( NULL == pthis )
	{
		return;
	}

	if ( 0 != pthread_cond_init(pthis,
		( NULL != pattr ? (pthread_condattr_t*)(pattr->getData()):NULL )) )
	{
		delete pthis;
		return;
	}

	m_pData = pthis;
#else
	__PWERRNO_NOIMPL();
#endif
}

PWCondition::~PWCondition()
{
#if defined(HAVE_POSIX_CONDITION)
	if ( m_pData )
	{
		pthread_cond_t* pthis((pthread_cond_t*)m_pData);
		pthread_cond_destroy(pthis);
		delete pthis;
		m_pData = NULL;
	}
#else
	__PWERRNO_NOIMPL();
#endif
}

void
PWCondition::signal(void)
{
#if defined(HAVE_POSIX_CONDITION)
	pthread_cond_signal((pthread_cond_t*)m_pData);
#else
	__PWERRNO_NOIMPL();
#endif
}

void
PWCondition::broadcast(void)
{
#if defined(HAVE_POSIX_CONDITION)
	pthread_cond_broadcast((pthread_cond_t*)m_pData);
#else
	__PWERRNO_NOIMPL();
#endif
}

void
PWCondition::wait(PWMutex& mutex)
{
#if defined(HAVE_POSIX_CONDITION)
	pthread_cond_wait((pthread_cond_t*)m_pData,
		(pthread_mutex_t*)mutex.getData());
#else
	__PWERRNO_NOIMPL();
#endif
}

bool
PWCondition::wait(PWMutex& mutex, struct timespec& ts)
{
#if defined(HAVE_POSIX_CONDITION)
	return 0 != pthread_cond_timedwait(
		(pthread_cond_t*)m_pData,
		(pthread_mutex_t*)mutex.getData(),
		&ts);
#else
	__PWERRNO_NOIMPL();
	return false;
#endif
}

bool
PWCondition::wait(PWMutex& mutex, size_t msec)
{
#if defined(HAVE_POSIX_CONDITION)
	struct timespec ts;
	ts.tv_sec = msec / 1000;
	ts.tv_nsec = (msec % 1000) * 1000000L;
	return 0 != pthread_cond_timedwait(
		(pthread_cond_t*)m_pData,
		(pthread_mutex_t*)mutex.getData(),
		&ts);
#else
	__PWERRNO_NOIMPL();
	return false;
#endif
}

};//namespace purewell

